package com.mmg.spzx.common.log.aspect;

import com.mmg.spzx.common.log.annotation.Log;
import com.mmg.spzx.common.log.service.AsyncOperLogService;
import com.mmg.spzx.common.log.utils.LogUtil;
import com.mmg.spzx.model.entity.system.SysOperLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 环绕通知切面类定义
 * 2023/11/20：bug1
 * 如果在LogAspect.class类上加上@Component注解进行注册标注，那么该类会被自动注册到Spring容器中，无需再使用@Import注解导入。
 * @Component注解是Spring框架提供的通用的组件扫描和注册注解，用于将一个类声明为Spring容器的组件。当一个类被@Component注解标记后，Spring会自动扫描并将其实例化并加入到容器中。
 * 因此，如果在LogAspect.class上添加了@Component注解，Spring会自动将其作为一个组件进行注册，不需要额外使用@Import注解来导入。
 */
@Aspect
@Slf4j
public class LogAspect {

    @Autowired
    private AsyncOperLogService asyncOperLogService;

    @Around(value = "@annotation(sysLog)")
    public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog) {

        // 构建前置参数
        SysOperLog sysOperLog = new SysOperLog();

        LogUtil.beforeHandleLog(sysLog, joinPoint, sysOperLog);

        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
            // 执行业务方法
            LogUtil.afterHandlLog(sysLog, proceed, sysOperLog, 0, null);
            // 构建响应结果参数
        } catch (Throwable e) {                                 // 代码执行进入到catch中，
            // 业务方法执行产生异常
            e.printStackTrace();                                // 打印异常信息
            LogUtil.afterHandlLog(sysLog, proceed, sysOperLog, 1, e.getMessage());
            throw new RuntimeException();
        }

        // 保存日志数据
        asyncOperLogService.saveSysOperLog(sysOperLog);

        // 返回执行结果
        return proceed;
    }
}
